From 4d9d3eeb7c93d8e1e3114b81c91253eb1250004a Mon Sep 17 00:00:00 2001 From: Julien Grall Date: Tue, 28 Apr 2015 15:32:33 +0100 Subject: [PATCH] xen/passthrough: iommu_deassign_device_dt: By default reassign device to nobody Currently, when the device is deassigned from a domain, we directly reassign to DOM0. As the device may not have been correctly reset, this may lead to corruption or expose some part of DOM0 memory. Also, we may have no way to reset some platform devices. If Xen reassigns the device to "nobody", it may receive some global/context fault because the transaction has failed (indeed the context has been marked invalid). Unfortunately there is no simple way to quiesce a buggy hardware. I think we could live with that for a first version of platform device passthrough. DOM0 will have to issue an hypercall to assign the device to itself if it wants to use it. Signed-off-by: Julien Grall Acked-by: Stefano Stabellini Acked-by: Ian Campbell --- xen/drivers/passthrough/arm/smmu.c | 8 +++++++- xen/drivers/passthrough/device_tree.c | 9 +++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/xen/drivers/passthrough/arm/smmu.c b/xen/drivers/passthrough/arm/smmu.c index 8a9b58b978..65de50bebe 100644 --- a/xen/drivers/passthrough/arm/smmu.c +++ b/xen/drivers/passthrough/arm/smmu.c @@ -2692,7 +2692,7 @@ static int arm_smmu_reassign_dev(struct domain *s, struct domain *t, int ret = 0; /* Don't allow remapping on other domain than hwdom */ - if (t != hardware_domain) + if (t && t != hardware_domain) return -EPERM; if (t == s) @@ -2702,6 +2702,12 @@ static int arm_smmu_reassign_dev(struct domain *s, struct domain *t, if (ret) return ret; + if (t) { + ret = arm_smmu_assign_dev(t, devfn, dev); + if (ret) + return ret; + } + return 0; } diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c index 05ab274305..0ec4103c37 100644 --- a/xen/drivers/passthrough/device_tree.c +++ b/xen/drivers/passthrough/device_tree.c @@ -80,15 +80,12 @@ int iommu_deassign_dt_device(struct domain *d, struct dt_device_node *dev) spin_lock(&dtdevs_lock); - rc = hd->platform_ops->reassign_device(d, hardware_domain, - 0, dt_to_dev(dev)); + rc = hd->platform_ops->reassign_device(d, NULL, 0, dt_to_dev(dev)); if ( rc ) goto fail; - list_del(&dev->domain_list); - - dt_device_set_used_by(dev, hardware_domain->domain_id); - list_add(&dev->domain_list, &domain_hvm_iommu(hardware_domain)->dt_devices); + list_del_init(&dev->domain_list); + dt_device_set_used_by(dev, DOMID_IO); fail: spin_unlock(&dtdevs_lock); -- 2.30.2